﻿//========================================================= 
/**@file Timer.h 
 * @brief 在Windows下和Linux下兼容的计时器(以ms为单位)
 * 
 * @date 2013-11-04   22:14:34 
 * @author Zhyioo
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_TIMER_H_
#define _LIBZHOUYB_TIMER_H_
//--------------------------------------------------------- 
#include "Define.h"

/* 头文件包含 */
#ifdef _MSC_VER
#   include <Windows.h>
#   pragma comment(lib, "User32.lib")
#else
#   include <sys/time.h>
#   include <unistd.h>
#endif
//--------------------------------------------------------- 
namespace zhou_yb {
namespace base {
//--------------------------------------------------------- 
/// 简易的计时器
class Timer
{
public:
    //----------------------------------------------------- 
    /// 时间量单位
    typedef ulong TickType;
    //----------------------------------------------------- 
#ifdef _MSC_VER
    /// Windows下获取时差
    static TickType TimeTick()
    {
        return static_cast<TickType>(::GetTickCount());
    }
    /// Windows下当前线程消息处理
    static void DoEvent()
    {
        MSG msg;
        while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
    }
    /// Windows下延时毫秒(每隔DEV_OPERATOR_INTERVAL做一次DoEvent)
    static void Wait(TickType timeMs)
    {
        // 将timeMs拆分成DEV_OPERATOR_INTERVAL进行延时 
        TickType time = timeMs / DEV_OPERATOR_INTERVAL;
        for(TickType i = 0;i < time; ++i)
        {
            Sleep(DEV_OPERATOR_INTERVAL);
            DoEvent();
        }
        time = timeMs % DEV_OPERATOR_INTERVAL;
        if(time > 0)
        {
            Sleep(time);
        }
    }
    /// 睡眠一段时间
    static void Delay(TickType timeMs)
    {
        if (timeMs < 1)
            return;
        Sleep(timeMs);
    }
#else
    /// Linux下获取时差
    static TickType TimeTick()
    {
        struct timeval _tv;
        gettimeofday(&_tv, NULL);
        TickType t = (1000 *_tv.tv_sec + (_tv.tv_usec/1000));
        return t;
    }
    /// Linux下延时毫秒 
    static void Wait(TickType timeMs)
    {
        if(timeMs < 1)
            return;
        usleep(static_cast<useconds_t>(timeMs * 1000));
    }
    /// 睡眠一段时间
    static void Delay(TickType timeMs)
    {
        Wait(timeMs);
    }
#endif
    //----------------------------------------------------- 
protected:
    /// 已经流逝的时间(ms)
    TickType _tickCount;
public:
    //----------------------------------------------------- 
    Timer()
    {
        _tickCount = TimeTick();
    }
    //----------------------------------------------------- 
    /// 重新启动时间 
    inline void Restart()
    {
        _tickCount = TimeTick();
    }
    /// 计算到当前的耗时(ms)
    TickType Elapsed() const
    {
        TickType t = TimeTick() - _tickCount;
        return t;
    }
    /// 返回耗时,并自动进入下一个计时状态
    TickType TickCount()
    {
        TickType tick = Elapsed();
        Restart();
        return tick;
    }
    //----------------------------------------------------- 
};
//--------------------------------------------------------- 
/**
 * @brief 以计数为基准的定时器
 * @date 2025-07-22 17:22
 */
class TickTimer
{
protected:
    uint _tick_count;
    uint _timeout_count;
public:
    TickTimer() : _tick_count(0), _timeout_count(0) {}

    inline void SetTimeout(uint timeout)
    {
        _timeout_count = timeout;
        _tick_count = 0;
    }
    inline void Forward(uint tick)
    {
        _tick_count = tick;
    }
    inline uint TickCount() const
    {
        return _tick_count;
    }
    inline void Restart()
    {
        _tick_count = 0;
    }
    inline bool IsElapsed() const
    {
        return _tick_count > _timeout_count;
    }
    /// 更新计时器并返回是否触发timeout事件
    bool Elapsed()
    {
        if (IsElapsed())
        {
            return true;
        }
        ++_tick_count;
        return false;
    }
};
//--------------------------------------------------------- 
} // namespace base
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_TIMER_H_
//========================================================= 
